package sch.frog.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class BeanUtil {
	
	/**
	 * Map 转 Bean
	 * @param clazz	bean的类型
	 * @param map	待转的map
	 * @return bean
	 * @throws ReflectiveOperationException
	 * @throws IntrospectionException
	 * @throws ParseException
	 */
	public static <T> T map2Bean(Class<T> clazz, Map<String, ?> map) throws ReflectiveOperationException, IntrospectionException, ParseException {
		BeanInfo beanInfo = Introspector.getBeanInfo(clazz); // 获取类属性
        T obj = clazz.newInstance(); // 创建 JavaBean 对象
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 给 JavaBean 对象的属性赋值
        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();

            if (map.containsKey(propertyName)) {
                // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
                Object value = map.get(propertyName);
                if(value == null) continue;

                Class<?> type = descriptor.getPropertyType();
                if(Date.class.isAssignableFrom(type)) {
					if(value instanceof String) {
						Date date = dateFormat.parse((String) value);
						descriptor.getWriteMethod().invoke(obj, date);
					}else if(value instanceof Date) {
						descriptor.getWriteMethod().invoke(obj, value);
					}
                }else{
                	Method writeMethod = descriptor.getWriteMethod();
                	if(writeMethod != null) {
                		writeMethod.invoke(obj, value);
                	}
                }
            }
        }
        return obj;
	}
	
	/**
	 * Bean 转 Map
	 * @param bean
	 * @return map
	 * @throws IntrospectionException
	 * @throws ReflectiveOperationException
	 */
	public static Map<String, Object> bean2Map(Object bean) throws IntrospectionException, ReflectiveOperationException {
		Class<? extends Object> type = bean.getClass();
        Map<String, Object> returnMap = new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(type);

        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean);
                if (result != null) {
                    returnMap.put(propertyName, result);
                } else {
                    returnMap.put(propertyName, null);
                }
            }
        }
        return returnMap;
	}
}
